package fag.editor;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;

import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.EventListenerList;

/**
 * Classe qui liste les images disponibles pour l'éditeur et en affiche un aperçu après un click.
 * @author Thibault
 *
 */

public class ResourceLoader extends JPanel implements MouseListener, ActionListener{
	
	// J'utilise la classe Ressource pour générer une liste de ressources (images + noms)
	private File directory;
	private ArrayList<Resource> resources;
	private Resource r;
	private JList imagesList;
	private DefaultListModel model;
	private JFileChooser jfc;
	private JButton imageDirectory;
	private JScrollPane scrollPane;
	private JLabel label;
	private String imageURL = null;
	
	private final static int DEFAULT_WIDTH = 80;
	private final static int DEFAULT_HEIGHT = 500;
	
	protected final static String ACTION_LOAD_IMAGE = "LoadImage";
	
	private final EventListenerList listeners = new EventListenerList();
	
	/**
	 * Constructeur par default
	 * @param pathname, le chemin d'accès au répertoire images (src/imgs)
	 */
	public ResourceLoader(String pathname)
	{
		resources = new ArrayList<Resource>();
		model = new DefaultListModel();
		imagesList = new JList(model);
		scrollPane = new JScrollPane(imagesList);
		scrollPane.setPreferredSize(new Dimension(80,360));
		label = new JLabel();
		label.setPreferredSize(new Dimension(80,80));
		imageDirectory = new JButton(new ImageIcon(getClass().getResource("/imgs/folder.png"),"FolderIcon"));
		imageDirectory.setPreferredSize(new Dimension(40,40));
		jfc = new JFileChooser(new File("src/imgs"));
		jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		
		// On écoute les actions sur le JList et le bouton
		imagesList.addMouseListener(this);
		imageDirectory.addActionListener(this);
		
		initializeFiles(pathname);
		
		for(int i=0;i<resources.size();i++)
			model.addElement(resources.get(i).getName());
		
		//On ajoute le bouton de selection du dossier images, la liste et l'aperçu de l'image
		add(label);
		add(scrollPane);
	    add(imageDirectory);
	}
	
	/**
	 * Créer la liste de ressources (images) disponibles
	 * @param pathname
	 */
	public void initializeFiles(String pathname)
	{
		// On supprime tout le contenu de la liste avant de la remplir avec les ressources du dossier sélectionné.
		resources.clear();
		directory = new File(pathname);
		
		File[] files = directory.listFiles();
		for(int i=0;i<files.length;i++)
		{
			if(files[i].isFile() && files[i].getName().endsWith(".png")) // On authorise uniquement l'extension .png pour les images
			{
				r = new Resource(); 
				try {
					// On ajoute à la liste des ressources la ressource courante
					resources.add(r.load(files[i].getAbsolutePath()));
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * Accesseur de l'url (absolute path) de l'image double cliquée
	 * @return
	 */
	public String getImageURL()
	{
		return imageURL;
	}
	
	@Override
	public Dimension preferredSize() {
		
		return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
	}
	
	/**
	 * Ajout listener
	 * @param listener
	 */
	public void addActionListener(ActionListener listener) {
		
		listeners.add(ActionListener.class,listener);
	}
	
	/**
	 * Choix du dossier où se trouve les images
	 */
	public  void actionPerformed(ActionEvent e)
	{
		if(e.getSource() == imageDirectory)
		{
			int ret = jfc.showOpenDialog(this);
			if(ret == JFileChooser.APPROVE_OPTION)
			{
				model.removeAllElements(); // on vide la liste
			    initializeFiles(jfc.getSelectedFile().getPath()); // initialisation des ressources du dossier sélectionné
			    
				// On ajoute ça à la JList
				for(int i=0;i<resources.size();i++)
					model.addElement(resources.get(i).getName());

			}
		}
	}
	
	/**
	 * Suppression listener
	 * @param listener
	 */
	public void removeActionListener(ActionListener listener) {
		
		listeners.remove(ActionListener.class, listener);
	}

    /**
     * Gestion du clic souris 
     * 1 clic = aperçu de l'image, 2 clics et on charge l'image dans l'éditeur
     */
	@Override
	public void mouseClicked(MouseEvent e) {

		int index = imagesList.getSelectedIndex();
		Image i = resources.get(index).getImage();
		int width = i.getWidth(null);
		int height = i.getHeight(null);
		
		if(width > 80 || height > 80) {
			
			i = scale(i,80,80);
		}

		if(i != null)
			setImage(i); // On raffraichit l'image
		
		// Si double clic
		if (e.getClickCount() == 2)
		{
			imageURL = resources.get(index).getPathName();
			loadImage();
		}
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {} 
	
	@Override
	public void mouseExited(MouseEvent arg0) {}

	@Override
	public void mousePressed(MouseEvent arg0) {} 

	@Override
	public void mouseReleased(MouseEvent arg0) {}  
	
	/**
	 * On met à jour l'affichage
	 * @param i
	 */
	public void setImage(Image i) {
        label.setIcon(new ImageIcon(i));
	}
	
	public static Image scale(Image source, int width, int height) {
	    /* On crée une nouvelle image aux bonnes dimensions. */
	    BufferedImage buf = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

	    /* On dessine sur le Graphics de l'image bufferisée. */
	    Graphics2D g = buf.createGraphics();
	    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
	    g.drawImage(source, 0, 0, width, height, null);
	    g.dispose();

	    /* On retourne l'image bufferisée, qui est une image. */
	    return buf;
	}
	
	protected void loadImage() {
		
		for(ActionListener listener : listeners.getListeners(ActionListener.class))
			listener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_LAST + 1, ACTION_LOAD_IMAGE));
	}
}